package com.alcatel_lucent.osp.service;

import com.alcatel_lucent.osp.model.User;
import com.opensymphony.xwork2.util.ArrayUtils;
import net.sf.json.JSON;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.TransformerUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.sql.Timestamp;
import java.util.*;

/**
 * User: guoshunw
 * Date: 13-10-11
 * Time: 上午10:12
 */

@Service
public class UserServiceImpl extends BaseServiceImpl implements UserService {

    @Autowired
    private JSONService jsonService;

    @Autowired
    LDAPService ldapService;

    private static Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    public User findUserByCSLorCIL(String cslOrCil) {
        if (StringUtils.isBlank(cslOrCil)) return null;
        User user;
        List<String> nameTokens = Arrays.asList(cslOrCil.split("\\s"));

        if (nameTokens.size() < 2) {
            String hql = "from User where csl = :csl";
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("csl", cslOrCil);
            user = (User) dao.retrieveOne(hql, params);
            if (null != user) return user;
        }
        String hql = "from User where ";

        int index = 0;
        for (String nameToken : nameTokens) {
            if (index > 0) hql += "and ";
            hql += "upper(cil) like upper('%" + nameToken + "%') ";
            index++;
        }
        user = (User) dao.retrieveOne(hql);
        return user;
    }

    @Override
    public Collection<User> findUserByKey(String key) {
//        String hql = "from User where csl like :cslOrCil or cil  like :cslOrCil";
//        Map<String, Object> params = new HashMap<String, Object>();
//        params.put("cslOrCil", "%" + key + "%");
//        return dao.retrieve(hql, params);
        return ldapService.findUserByCILParts(key);
    }

    @Override
    public JSON searchUsersByKey(String key) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        return jsonService.toJSON(findUserByKey(key), "csl, cil, email");
    }

    /**
     * Get users by their CSLs, save user if it isn't in DB.
     *
     * @param csls user csl
     * @return user collection
     */
    @Override
    public Collection<User> getAndSaveUsersByCSL(String[] csls) {
        Collection<User> users = new ArrayList<User>();
        if (ArrayUtils.isEmpty(csls)) return users;
        String hql = "from User where csl in :csls";
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("csls", Arrays.asList(csls));
        Collection<User> usersInDB = dao.retrieve(hql, params);
        users.addAll(usersInDB);
        Collection<String> CSLsInDB = CollectionUtils.collect(users, TransformerUtils.invokerTransformer("getCsl"));
        Collection<String> CSLsNotInDB = CollectionUtils.subtract(Arrays.asList(csls), CSLsInDB);
        log.info("CSL not in db: {}", CSLsNotInDB);
        //create users which are not in local db
        for (String csl : CSLsNotInDB) {
            User user = ldapService.findUserByCSLOrCIL(csl);
            user.setCreateTime(new Timestamp(System.currentTimeMillis()));
            user.setActive(true);
            log.info("Create user: {}", user);
            user = (User) dao.create(user);
            users.add(user);
        }
        return users;
    }

    public JSON saveUserByCSL(String csl) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        User user = (User) dao.retrieve(User.class, csl);
        if (null != user) {
            return jsonService.toJSON(user, "csl, cil, email");
        }
        user = ldapService.findUserByCSLOrCIL(csl);
        user.setCreateTime(new Timestamp(System.currentTimeMillis()));
        user.setActive(true);
        log.info("Create user: {}", user);
        user = (User) dao.create(user);
        return jsonService.toJSON(user, "csl, cil, email");
    }


    /**
     * Validate reporter
     */
    @Override
    public JSON validateReporter(String cslOrCil) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //Avoid search in local db to prevent multi users query can't be found
//        User user = findUserByCSLorCIL(cslOrCil);
//        if (null != user) {
//            return jsonService.toJSON(Arrays.asList(user), "csl, cil, email");
//        }

        // user not found in local database, the we try to find them in ldap db
        List<User> users = ldapService.findUserByCILParts(cslOrCil);
        // not of them found in ldap db
        return jsonService.toJSON(users, "csl, cil, email");
    }


}
